package indi.mozping.query;

import indi.mozping.dao.CarMapper;
import indi.mozping.entity.BaseObject;
import indi.mozping.entity.Car;
import indi.mozping.querybean.ColorQueryBean;
import indi.mozping.querybean.FieldQueryBean;
import indi.mozping.querybean.MultiFieldQueryBean;
import indi.mozping.util.GlobalConst;
import indi.mozping.util.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author by mozping
 * @Classname QueryCar
 * @Description ��ѯ������ɫ����
 * @Date 2019/6/27 11:10
 */
public class QueryCar {


    private static Random random = new Random();

    /**
     * ���ݳ�����ɫ��ѯ���ݿ�ӿڣ�����ǲ�����ѯ����ô������������������ȡһ������
     *
     * @param colorQueryBean ��ѯ������ɫ����������
     * @param concurrent     ������ѯ��Ŀ��Ĭ��1
     * @param printDetail    �Ƿ��ӡ��ѯ�����Ĭ��false����ӡ������ӡ���ֻ���ӡ�����������ӡ����Ὣ��ѯ���ȫ����ӡ
     * @date 2019/6/27 11:12
     */
    public static void queryCarColor(List<ColorQueryBean> colorQueryBean,
                                     int concurrent, int numPerThread, boolean printDetail) {

        int threadNum = getConcurrent(concurrent);
        for (int i = 1; i <= threadNum; i++) {
            new Thread(new QueryCarColorThread(colorQueryBean, numPerThread, printDetail)).start();
        }
    }


    public static void queryCarField(List<FieldQueryBean> fieldQueryBeanList,
                                     int concurrent, int numPerThread, boolean printDetail) {

        int threadNum = getConcurrent(concurrent);
        for (int i = 1; i <= threadNum; i++) {
            new Thread(new QueryCarFieldThread(fieldQueryBeanList, numPerThread, printDetail)).start();
        }
    }

    public static void queryCarFieldMulti(List<MultiFieldQueryBean> multiFieldQueryBean,
                                          int concurrent, int numPerThread, boolean printDetail) {

        int threadNum = getConcurrent(concurrent);
        for (int i = 1; i <= threadNum; i++) {
            new Thread(new QueryCarMultiFieldThread(multiFieldQueryBean, numPerThread, printDetail)).start();
        }
    }


    static class QueryCarColorThread implements Runnable {

        List<ColorQueryBean> colorQueryBean;
        int numPerThread;
        boolean printDetail;

        public QueryCarColorThread(List<ColorQueryBean> colorQueryBean, int numPerThread, boolean printDetail) {
            this.colorQueryBean = colorQueryBean;
            this.numPerThread = numPerThread;
            this.printDetail = printDetail;
        }

        @Override
        public void run() {
            SqlSession sqlSession =
                    SqlSessionFactoryUtil.getSqlSessionFactoryInstaceByConfig(GlobalConst.CONFIG_FILE_PATH).openSession();
            CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
            ArrayList<Long> timeList = new ArrayList<>(numPerThread);
            long timeTotal = 0L;
            for (int i = 0; i < numPerThread; i++) {
                ColorQueryBean randomMember = colorQueryBean.get(random.nextInt(colorQueryBean.size()));
                long begin = System.currentTimeMillis();
                ArrayList<Car> cars = carMapper.queryCarByColor(randomMember);
                long end = System.currentTimeMillis();
                timeList.add(end - begin);
                SqlSessionFactoryUtil.closeSession(sqlSession);
                dealResult(cars, printDetail);
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ������ѯ" + numPerThread + "�Σ���ʱ���Ϊ");
            for (Long time : timeList) {
                System.out.print(time + "  ");
                timeTotal += time;
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ��ѯƽ����ʱΪ:" + (timeTotal / numPerThread) + " ms");
        }
    }


    static class QueryCarIdThread implements Runnable {

        List<List<String>> idsList;
        int numPerThread;
        boolean printDetail;

        public QueryCarIdThread(List<List<String>> idsList, int numPerThread, boolean printDetail) {
            this.idsList = idsList;
            this.numPerThread = numPerThread;
            this.printDetail = printDetail;
        }

        @Override
        public void run() {
            SqlSession sqlSession =
                    SqlSessionFactoryUtil.getSqlSessionFactoryInstaceByConfig(GlobalConst.CONFIG_FILE_PATH).openSession();
            CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
            ArrayList<Long> timeList = new ArrayList<>(numPerThread);
            long timeTotal = 0L;
            for (int i = 0; i < numPerThread; i++) {
                List<String> ids = idsList.get(random.nextInt(idsList.size()));
                long begin = System.currentTimeMillis();
                List<Car> cars = carMapper.selectCarById(ids);
                long end = System.currentTimeMillis();
                timeList.add(end - begin);
                SqlSessionFactoryUtil.closeSession(sqlSession);
                dealResult(cars, printDetail);
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ������ѯ" + numPerThread + "�Σ���ʱ���Ϊ");
            for (Long time : timeList) {
                System.out.print(time + "  ");
                timeTotal += time;
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ��ѯƽ����ʱΪ:" + (timeTotal / numPerThread) + " ms");
        }
    }


    static class QueryCarFieldThread implements Runnable {

        List<FieldQueryBean> fieldQueryBeanList; //colorQueryBean
        int numPerThread;
        boolean printDetail;

        public QueryCarFieldThread(List<FieldQueryBean> fieldQueryBeanList, int numPerThread, boolean printDetail) {
            this.fieldQueryBeanList = fieldQueryBeanList;
            this.numPerThread = numPerThread;
            this.printDetail = printDetail;
        }

        @Override
        public void run() {
            SqlSession sqlSession =
                    SqlSessionFactoryUtil.getSqlSessionFactoryInstaceByConfig(GlobalConst.CONFIG_FILE_PATH).openSession();
            CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
            ArrayList<Long> timeList = new ArrayList<>(numPerThread);
            long timeTotal = 0L;
            for (int i = 0; i < numPerThread; i++) {
                FieldQueryBean fieldQueryBean = fieldQueryBeanList.get(random.nextInt(fieldQueryBeanList.size()));
                long begin = System.currentTimeMillis();
                List<Car> cars = carMapper.selectCarByField(fieldQueryBean);
                long end = System.currentTimeMillis();
                timeList.add(end - begin);
                SqlSessionFactoryUtil.closeSession(sqlSession);
                dealResult(cars, printDetail);
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ������ѯ" + numPerThread + "�Σ���ʱ���Ϊ");
            for (Long time : timeList) {
                System.out.print(time + "  ");
                timeTotal += time;
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ��ѯƽ����ʱΪ:" + (timeTotal / numPerThread) + " ms");
        }
    }

    static class QueryCarMultiFieldThread implements Runnable {

        List<MultiFieldQueryBean> multiFieldQueryBeanList;
        int numPerThread;
        boolean printDetail;

        public QueryCarMultiFieldThread(List<MultiFieldQueryBean> multiFieldQueryBeanList,
                                        int numPerThread, boolean printDetail) {
            this.multiFieldQueryBeanList = multiFieldQueryBeanList;
            this.numPerThread = numPerThread;
            this.printDetail = printDetail;
        }

        @Override
        public void run() {
            SqlSession sqlSession =
                    SqlSessionFactoryUtil.getSqlSessionFactoryInstaceByConfig(GlobalConst.CONFIG_FILE_PATH).openSession();
            CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
            ArrayList<Long> timeList = new ArrayList<>(numPerThread);
            long timeTotal = 0L;
            for (int i = 0; i < numPerThread; i++) {
                MultiFieldQueryBean multiFieldQueryBean =
                        multiFieldQueryBeanList.get(random.nextInt(multiFieldQueryBeanList.size()));
                long begin = System.currentTimeMillis();
                List<Car> cars = carMapper.selectCarByMultiField(multiFieldQueryBean);
                long end = System.currentTimeMillis();
                timeList.add(end - begin);
                SqlSessionFactoryUtil.closeSession(sqlSession);
                dealResult(cars, printDetail);
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ������ѯ" + numPerThread + "�Σ���ʱ���Ϊ");
            for (Long time : timeList) {
                System.out.print(time + "  ");
                timeTotal += time;
            }
            System.out.println("�̣߳�[" + Thread.currentThread() + "] ��ѯƽ����ʱΪ:" + (timeTotal / numPerThread) + " ms");
        }
    }


    private static void dealResult(List<? extends BaseObject> list, boolean printDetail) {
        if (printDetail) {
            for (BaseObject object : list) {
                System.out.println(object);
            }
        } else {
            System.out.println("�߳�: [" + Thread.currentThread() + "] ��ѯ�������:" + list.size());
        }
    }


    private static Object getRandomMember(List<? extends Object> objects) {
        int index = random.nextInt(objects.size());
        return objects.get(index);
    }

    private static int getConcurrent(int concurrent) {
        if (concurrent == 10) {
            return 10;
        } else if (concurrent == 5) {
            return 5;
        } else if (concurrent == 3) {
            return 3;
        } else {
            return 1;
        }
    }
}